package com.cbianc.structure.proxy.jdk

/*
* 在有些情况下，一个客户不能或者不想直接访问另一个对象，这时需要找一个中介帮忙完成某项任务，这个中介就是代理对象
*
* 在软件设计中，使用代理模式的例子也很多，例如，要访问的远程对象比较大（如视频或大图像等），其下载要花很多时间。还有因为安全原因需要屏蔽客户端直接访问真实对象，如某单位的内部数据库等。
*
* 代理模式的定义：由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时，访问对象不适合或者不能直接引用目标对象，代理对象作为访问对象和目标对象之间的中介。

代理模式的主要优点有：
    代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用；
    代理对象可以扩展目标对象的功能；
    代理模式能将客户端与目标对象分离，在一定程度上降低了系统的耦合度，增加了程序的可扩展性

* ==> 动态代理方式 <==
其主要缺点是：
    代理模式会造成系统设计中类的数量增加
    在客户端和目标对象之间增加一个代理对象，会造成请求处理速度变慢；
    增加了系统的复杂度；
    *
* */
/**
 * Subject
 * 代理模式的结构比较简单，主要是通过定义一个继承抽象主题的代理来包含真实主题，从而实现对真实主题的访问，下面来分析其基本结构和实现方法。

 * @constructor Create empty Subject
 */

fun main() {
    val proxy = Proxy()
    proxy.Request()
}

// 抽象主题（Subject）类：通过接口或抽象类声明真实主题和代理对象实现的业务方法
internal interface Subject {
    fun Request()
}

//真实主题 实现了抽象主题中的具体业务，是代理对象所代表的真实对象，是最终要引用的对象。
internal class RealSubject : Subject {
    override fun Request() {
        println("访问真实主题方法...")
    }
}

//代理 供了与真实主题相同的接口，其内部含有对真实主题的引用，它可以访问、控制或扩展真实主题的功能。
internal class Proxy : Subject {
    private var realSubject: RealSubject? = null
    override fun Request() {
        if (realSubject == null) {
            realSubject = RealSubject()
        }
        preRequest()
        realSubject!!.Request()
        postRequest()
    }

    fun preRequest() {
        println("访问真实主题之前的预处理。")
    }

    fun postRequest() {
        println("访问真实主题之后的后续处理。")
    }
}